package com.herench.bs.transfer;

import com.herench.bs.transfer.Dialect;
import com.herench.bs.utils.DataFormatUtils;
import org.apache.cxf.endpoint.Client;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.*;

/**
 * Created by ThinkPad on 2017/9/5.
 */
public class DoctorAppointScheduleTransfer extends AbstractTransfer {

    public DoctorAppointScheduleTransfer(String method, Client client,String messageMethod)  {
        super(method, client,messageMethod);
    }

    @Override
    public String toInvokeMessage(Map<String, Object> params) throws Exception {
        Document document = getTplDoc(getMethod());
        Element dataRow = document.getRootElement().element("CommitData").addElement("Data").addElement("DataRow");
        String startDate = (String) params.get("startDate");
        dataRow.addAttribute("CLINIC_DATE_START", startDate);
        String endDate = (String) params.get("endDate");
        endDate = endDate != null ? endDate : "";
        dataRow.addAttribute("CLINIC_DATE_END", endDate);
        String deptCode = (String) params.get("deptCode");
        dataRow.addAttribute("DEPT_CODE", deptCode);
        String doctorCode = (String) params.get("doctorCode");
        dataRow.addAttribute("DOCTOR_CODE", doctorCode);
        return document.asXML();
    }

    @Override
    public Map<String, Object> toResultMessage(String resMsg) throws Exception {
        Map<String, Object> resMap = new HashMap<>();
        Document document = DocumentHelper.parseText(resMsg);
        Element resultInfo = document.getRootElement().element("Result").element("Info");
        String executeStatus = resultInfo.attributeValue("EXECUTE_STATUS");
        String executeMessage = resultInfo.attributeValue("EXECUTE_MESSAGE");
        if (executeStatus.equals("0")){
            List<Element> dataRows = document.getRootElement().element("ReturnData").element("Data").elements();
            TreeSet<ClinicDate> clinicDateSet = new TreeSet<>();
            List<DoctorAppointScheduleInnerMessage> innerMessageList = new ArrayList<>();

            if (dataRows != null) {
                for (Element dataRowEl : dataRows) {
                    DoctorAppointScheduleInnerMessage innerMessage = new DoctorAppointScheduleInnerMessage(dataRowEl);
                    innerMessageList.add(innerMessage);
                    ClinicDate clinicDate = new ClinicDate();
                    clinicDate.setAmpm(Dialect.getAmpmCode(innerMessage.getTimeDesc()));
                    clinicDate.setAmpmName(innerMessage.getTimeDesc());
                    clinicDate.setSchDate(DataFormatUtils.getSimpleDayString(innerMessage.getClinicDate()));
                    clinicDate.setDayOfWeek(Dialect.getDayOfWeek(DataFormatUtils.parserDay(innerMessage.getClinicDate())));
                    clinicDate.setCategorCode(Dialect.getClinicTypeCode(innerMessage.getClinicType()));
                    clinicDate.setCategorName(innerMessage.getClinicType()+"号");
                    clinicDate.setRegFee(innerMessage.getRegistFee());
                    clinicDate.setClinicLabel(innerMessage.getClinicLabel());
                    resMap.put("categorCode",Dialect.getClinicTypeCode(innerMessage.getClinicType()));
                    resMap.put("categorName",innerMessage.getClinicType());
                    resMap.put("doctorCode",innerMessage.getDoctorCode());
                    resMap.put("doctorName",innerMessage.getDoctor());
                    resMap.put("deptName",innerMessage.getDeptName());
                    resMap.put("deptCode",innerMessage.getClinicDept());
                    clinicDateSet.add(clinicDate);
                }
                for (ClinicDate tempClinicDate:clinicDateSet){
                    List<TimeDesc> timeDescList = new ArrayList<>();
                    tempClinicDate.setTimeDescList(timeDescList);
                    for (DoctorAppointScheduleInnerMessage tempMessage : innerMessageList) {
                        if (tempClinicDate.getSchDate().equals(DataFormatUtils.getSimpleDayString(tempMessage.getClinicDate())) && tempClinicDate.getAmpmName().equals(tempMessage.getTimeDesc())) {
                            TimeDesc timeDesc = new TimeDesc();
//                            timeDesc.setSchDate(tempClinicDate.getSchDate());
                            timeDesc.setRegFee(tempMessage.getRegistFee());
                            timeDesc.setSchDate(tempMessage.getClinicDate());
                            timeDesc.setTimeDesc( tempMessage.getHourStart() + "~" + tempMessage.getHourEnd());
                            timeDesc.setAmpm(Dialect.getAmpmCode(tempMessage.getTimeDesc()));
                            timeDesc.setCategorCode(Dialect.getClinicTypeCode(tempMessage.getClinicType()));
                            timeDesc.setDisNo(tempMessage.getNumCanBeRegisted());
                            timeDesc.setAppointmentNum(tempMessage.getAppointmentNum());
//                            timeDesc.setNumRemain(Integer.valueOf(tempClinicDate.getDisNo()) - Integer.valueOf(tempMessage.getAppointmentNum())+"");
                            timeDescList.add(timeDesc);
                            tempClinicDate.setDisNo(Integer.valueOf(tempClinicDate.getDisNo()) + Integer.valueOf(tempMessage.getNumCanBeRegisted())+"");
                        }
                    }
                }

            }
            resMap.put("clinicDateList", clinicDateSet);
            return resMap;
        }else {
            resMap.put("code",executeStatus);
            resMap.put("message",executeMessage);
            return resMap;
        }
    }

    private class DoctorAppointScheduleInnerMessage implements InnerMessage {
        private String clinicLabel;//号表
        private String clinicDate;  //出诊日期
        private String timeDesc; //时段
        private String hourStart;//开始时间
        private String hourEnd;//结束时间
        private String appointmentNum;   //预约数
        private String numCanBeRegisted;
        private String registFee;
        private String clinicFee;
        private String otherFee;
        private String clinicDept;
        private String deptName;
        private String doctorCode;
        private String doctor;
        private String clinicType;


        public DoctorAppointScheduleInnerMessage(Element element) {
            this.clinicLabel = element.attributeValue("CLINIC_LABEL");
            this.clinicDate = element.attributeValue("CLINIC_DATE");
            this.timeDesc = element.attributeValue("TIME_DESC");
            this.hourStart = element.attributeValue("HOUR_START");
            this.hourEnd = element.attributeValue("HOUR_END");
            this.appointmentNum = element.attributeValue("APPOINTMENT_NUM");
            this.numCanBeRegisted = element.attributeValue("NUM_CAN_BE_REGISTED");
            this.registFee = element.attributeValue("REGIST_FEE");
            this.clinicFee = element.attributeValue("CLINIC_FEE");
            this.otherFee = element.attributeValue("OTHER_FEE");
            this.clinicDept = element.attributeValue("CLINIC_DEPT");
            this.deptName = element.attributeValue("DEPT_NAME");
            this.doctorCode = element.attributeValue("DOCTOR_CODE");
            this.doctor = element.attributeValue("DOCTOR");
            this.clinicType = element.attributeValue("CLINIC_TYPE");
        }

        public String getClinicLabel() {
            return clinicLabel;
        }

        public void setClinicLabel(String clinicLabel) {
            this.clinicLabel = clinicLabel;
        }

        public String getClinicDate() {
            return clinicDate;
        }

        public void setClinicDate(String clinicDate) {
            this.clinicDate = clinicDate;
        }

        public String getTimeDesc() {
            return timeDesc;
        }

        public void setTimeDesc(String timeDesc) {
            this.timeDesc = timeDesc;
        }

        public String getHourStart() {
            return hourStart;
        }

        public void setHourStart(String hourStart) {
            this.hourStart = hourStart;
        }

        public String getHourEnd() {
            return hourEnd;
        }

        public void setHourEnd(String hourEnd) {
            this.hourEnd = hourEnd;
        }

        public String getAppointmentNum() {
            return appointmentNum;
        }

        public void setAppointmentNum(String appointmentNum) {
            this.appointmentNum = appointmentNum;
        }

        public String getNumCanBeRegisted() {
            return numCanBeRegisted;
        }

        public void setNumCanBeRegisted(String numCanBeRegisted) {
            this.numCanBeRegisted = numCanBeRegisted;
        }

        public String getRegistFee() {
            return registFee;
        }

        public void setRegistFee(String registFee) {
            this.registFee = registFee;
        }

        public String getClinicFee() {
            return clinicFee;
        }

        public void setClinicFee(String clinicFee) {
            this.clinicFee = clinicFee;
        }

        public String getOtherFee() {
            return otherFee;
        }

        public void setOtherFee(String otherFee) {
            this.otherFee = otherFee;
        }

        public String getClinicDept() {
            return clinicDept;
        }

        public void setClinicDept(String clinicDept) {
            this.clinicDept = clinicDept;
        }

        public String getDeptName() {
            return deptName;
        }

        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }

        public String getDoctorCode() {
            return doctorCode;
        }

        public void setDoctorCode(String doctorCode) {
            this.doctorCode = doctorCode;
        }

        public String getDoctor() {
            return doctor;
        }

        public void setDoctor(String doctor) {
            this.doctor = doctor;
        }

        public String getClinicType() {
            return clinicType;
        }

        public void setClinicType(String clinicType) {
            this.clinicType = clinicType;
        }
    }

    private class ClinicDate implements InnerMessage, Comparable<ClinicDate> {
        private String schDate;
        private String dayOfWeek;
        private String ampm;
        private String ampmName;
        private String regFee;
        private String categorCode;
        private String categorName;
        private String clinicLabel;
        private String schState;//0、可预约 1、停诊 2、约满 3、有排班不可预约
        private String disNo ="0";
        private List<TimeDesc> timeDescList;

        public String getDisNo() {
            return disNo;
        }

        public void setDisNo(String disNo) {
            this.disNo = disNo;
        }

        public String getSchDate() {
            return schDate;
        }

        public void setSchDate(String schDate) {
            this.schDate = schDate;
        }

        public String getDayOfWeek() {
            return dayOfWeek;
        }

        public void setDayOfWeek(String dayOfWeek) {
            this.dayOfWeek = dayOfWeek;
        }

        public String getAmpm() {
            return ampm;
        }

        public void setAmpm(String ampm) {
            this.ampm = ampm;
        }

        public String getAmpmName() {
            return ampmName;
        }

        public void setAmpmName(String ampmName) {
            this.ampmName = ampmName;
        }

        public String getRegFee() {
            return regFee;
        }

        public void setRegFee(String regFee) {
            this.regFee = regFee;
        }

        public String getClinicLabel() {
            return clinicLabel;
        }

        public void setClinicLabel(String clinicLabel) {
            this.clinicLabel = clinicLabel;
        }

        public String getSchState() {
            if (Integer.valueOf(disNo) > 0) {
                return "0";
            } else {
                return "1";
            }
        }

        public List<TimeDesc> getTimeDescList() {
            return timeDescList;
        }

        public void setTimeDescList(List<TimeDesc> timeDescList) {
            this.timeDescList = timeDescList;
        }

        public void setSchState(String schState) {
            this.schState = schState;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            ClinicDate that = (ClinicDate) o;

            if (schDate != null ? !schDate.equals(that.schDate) : that.schDate != null) return false;
            if (dayOfWeek != null ? !dayOfWeek.equals(that.dayOfWeek) : that.dayOfWeek != null) return false;
            if (ampm != null ? !ampm.equals(that.ampm) : that.ampm != null) return false;
            if (ampmName != null ? !ampmName.equals(that.ampmName) : that.ampmName != null) return false;
            if (regFee != null ? !regFee.equals(that.regFee) : that.regFee != null) return false;
            return clinicLabel != null ? clinicLabel.equals(that.clinicLabel) : that.clinicLabel == null;
        }

        @Override
        public int hashCode() {
            int result = schDate != null ? schDate.hashCode() : 0;
            result = 31 * result + (dayOfWeek != null ? dayOfWeek.hashCode() : 0);
            result = 31 * result + (ampm != null ? ampm.hashCode() : 0);
            result = 31 * result + (ampmName != null ? ampmName.hashCode() : 0);
            result = 31 * result + (regFee != null ? regFee.hashCode() : 0);
            result = 31 * result + (clinicLabel != null ? clinicLabel.hashCode() : 0);
            return result;
        }

        @Override
        public int compareTo(ClinicDate o) {
            int schDateFlag = this.getSchDate().compareTo(o.getSchDate());
            if (schDateFlag!=0){
                return schDateFlag;
            }else {
                return this.getAmpm().compareTo(o.getAmpm());
            }

        }

        public String getCategorCode() {
            return categorCode;
        }

        public void setCategorCode(String categorCode) {
            this.categorCode = categorCode;
        }

        public String getCategorName() {
            return categorName;
        }

        public void setCategorName(String categorName) {
            this.categorName = categorName;
        }
    }


    private class TimeDesc implements InnerMessage, Comparable<TimeDesc> {
        private String schDate;
        private String timeDesc;
        private String disNo ="0";
        private String schState ;
        private String appointmentNum ;
        private String regFee ;
        private String numRemain ;
        private String ampm ;
        private String categorCode ;

        public String getAmpm() {
            return ampm;
        }

        public void setAmpm(String ampm) {
            this.ampm = ampm;
        }

        public String getCategorCode() {
            return categorCode;
        }

        public void setCategorCode(String categorCode) {
            this.categorCode = categorCode;
        }

        public String getRegFee() {
            return regFee;
        }

        public void setRegFee(String regFee) {
            this.regFee = regFee;
        }

        public String getSchDate() {
            return schDate;
        }

        public void setSchDate(String schDate) {
            this.schDate = schDate;
        }

        public String getTimeDesc() {
            return timeDesc;
        }

        public void setTimeDesc(String timeDesc) {
            this.timeDesc = timeDesc;
        }

        public String getDisNo() {
            return disNo;
        }

        public void setDisNo(String disNo) {
            this.disNo = disNo;
        }

        public String getAppointmentNum() {
            return appointmentNum;
        }

        public void setAppointmentNum(String appointmentNum) {
            this.appointmentNum = appointmentNum;
        }

        public void setNumRemain(String numRemain) {
            this.numRemain = numRemain;
        }

        public String getSchState() {
            if (Integer.valueOf(disNo) > 0) {
                return "0";
            } else {
                return "1";
            }
        }

        public void setSchState(String schState) {
            this.schState = schState;
        }


        @Override
        public int compareTo(TimeDesc o) {
            return this.getTimeDesc().compareTo(o.getTimeDesc());
        }
    }


}
